package com.gxa.clientkill.controller;

/*
 *
 *@author leijun
 *
 *@creating 2020/10/28 15:33
 *
 */

import com.gxa.clientkill.utils.JsonResult;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName TestController
 * @Description TODO
 * @Author 俊
 * @Date 2020/10/28 15:33
 * @Version 1.0
 */


@RestController
@RequestMapping("/sell")
public class TestController {


    //引入jedis/redis-data
    @Resource
    RedisTemplate redisTemplate;

    @RequestMapping(value="/t1",method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Map test1(){
        JsonResult jsonResult = new JsonResult();
        jsonResult.setCode("200");
        jsonResult.setMsg("eureka-client");
        jsonResult.setData("9094");
        return jsonResult.getValues();
    }

    //如果使用mysql，会在并发场景下出现超买超卖的情况
    //使用java的方式来防止该问题发生synchronized
    //String lock="lcok"
       /*synchronized (lock){

       }*/

    //分布式应用中，线程和锁都统统没用

    //考虑使用Redis，Redis是独立的服务，Redis特别适合高并发

    //10件羽绒服，开放给10000个人秒杀
    //准备表示库存的数据：10






    @PostMapping("/secondSell")
    public Map secondSell(){
        ValueOperations valueOperations = redisTemplate.opsForValue();

        //利用Redis加锁，核心利用NX机制
        Boolean lock = valueOperations.setIfAbsent("lock", true);

        //给用户的锁加上有效时间
        redisTemplate.expire("lock",10, TimeUnit.SECONDS);

//        Boolean lock = valueOperations.setIfAbsent("lock", true, 10, TimeUnit.SECONDS);

        //在实际业务场景中，上述两个操作：setIfAbsent和expire应该用原子级别的操作
        //valueOperations.set("lock",true,10,TimeUnit.SECONDS);
        if (lock){
            //当用户请求到达,判断库存>0
//            valueOperations.set("stock",10);
            Integer stock = (Integer) valueOperations.get("stock");
            System.out.println(stock);

            if (stock>0){
                //库存已经减少
                valueOperations.set("stock",--stock);
                System.out.println("秒杀成功，库存："+stock);
                JsonResult jsonResult = new JsonResult();
                jsonResult.setCode("200");
                jsonResult.setMsg("秒杀成功");

                //添加订单操作
//                valueOperations.set("stock",stock);
                //完成秒杀释放锁资源
                //如果要释放锁，必须是本人
                //原理：在此次发起中生成key（UUID），把key作为作为lock
                //判断当前lock的值是否和此次请求中的key是不是一致
                //如果相等，代表是操作者本人，释放
                //if (uuid.equals(valueOperations.get("lock")))
                redisTemplate.delete("lock");
                return jsonResult.getValues();

            }
        }
        //如果满足库存条件，抢购成功，库存-1

        //用户+id 记录到订单中

        return null;
    }
}
